package com.wsz.matching.utils;

import com.wsz.matching.fegin.StartGameFeginClient;
import com.wsz.pojo.dto.MatchingDto;
import com.wsz.pojo.dto.MatchingIdDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

@Component
public class MatchingPool extends Thread{
    private static List<MatchingDto> players = new LinkedList<>();
    private ReentrantLock lock  = new ReentrantLock();

    private static StartGameFeginClient startGameFeginClient;

    @Autowired
    public void setStartGameFeginClient(StartGameFeginClient startGameFeginClient){
        MatchingPool.startGameFeginClient = startGameFeginClient;
    }

    public void addPlayer(String userId,Integer Rating,String bot_id){
        lock.lock();
        try{
            MatchingDto matchingDto = new MatchingDto();
            matchingDto.setUserId(userId);
            matchingDto.setRanting(Rating);
            matchingDto.setBot_id(bot_id);
            matchingDto.setWaiting(0);
            players.add(matchingDto);
        }finally {
            lock.unlock();
        }
    }

    public void removePlayer(String userId){
        lock.lock();
        try{
            List<MatchingDto> newPlayer = new LinkedList<>();
            for (int i = 0; i < players.size(); i++) {
                if(!players.get(i).getUserId().equals(userId)){
                    newPlayer.add(players.get(i));
                }
            }
            players = newPlayer;
        }finally {
            lock.unlock();
        }
    }

    private void increaseWait(){
        for(MatchingDto player : players){
            player.setWaiting(player.getWaiting() + 1);
        }
    }

    private void matchPlayer(){
        int size = players.size();

        boolean[] user = new boolean[size];

        for (int i = 0; i < size; i++) {
            if(user[i]) continue;
            for (int j = i + 1; j < size; j++) {
                if(user[j]) continue;
                MatchingDto a = players.get(i);
                MatchingDto b = players.get(j);
                if(check(a,b)){
                    user[i] = user [j] = true;
                    sendResult(a,b);
                    break;
                }
            }
        }

        List<MatchingDto> newPlayer = new LinkedList<>();

        for (int i = 0; i < size; i++) {
            if(!user[i]) newPlayer.add(players.get(i));
        }

        players = newPlayer;
    }

    private Boolean check(MatchingDto a,MatchingDto b){
        int RantingDelta = Math.abs(a.getRanting() - b.getRanting());
        int wait = Math.max(a.getWaiting() , b.getWaiting());
        return wait * 10 >= RantingDelta;
    }


    private void sendResult(MatchingDto a,MatchingDto b){
        MatchingIdDto matchingIdDto = new MatchingIdDto();
        matchingIdDto.setAId(a.getUserId());
        matchingIdDto.setBId(b.getUserId());
        matchingIdDto.setABotId(a.getBot_id());
        matchingIdDto.setBBotId(b.getBot_id());
        startGameFeginClient.startGame(matchingIdDto);
    }


    @Override
    public void run() {
        while (true){
            try{
                Thread.sleep(1000);
                lock.lock();
                try{
                    increaseWait();
                    matchPlayer();
                }finally {
                    lock.unlock();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
